package com.sne.common.validator;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.base.CaseFormat;
import com.sne.common.entity.BaseModel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.stereotype.Component;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.Field;
import java.util.Arrays;

/**
 * @author fanghh
 * @date 2020/10/12
 */
@Slf4j
@Component
public class UniqueValidator implements ConstraintValidator<Unique, BaseModel> {

    private String[] fields;

    private String[] messages;

    @Override
    public boolean isValid(BaseModel baseModel, ConstraintValidatorContext context) {
        Class modelClass = baseModel.getClass();
        Field[] allFields = FieldUtils.getAllFields(modelClass);
        context.disableDefaultConstraintViolation();
        context.buildConstraintViolationWithTemplate(StringUtils.join(messages))
                .addConstraintViolation();
        QueryWrapper<Object> query = Wrappers.query();
        for (String field : fields) {
            String name = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, field);
            Arrays.stream(allFields).filter(x -> x.getName().equals(name)).findFirst().ifPresent(x -> {
                try {
                    x.setAccessible(true);
                    query.eq(field, x.get(baseModel));
                } catch (IllegalAccessException e) {
                    log.error("",e);
                }
            });
        }
        int count = baseModel.getId() == null ? baseModel.selectCount(query) :
                baseModel.selectCount(query.ne("id", baseModel.getId()));
        return count <= 0;
    }

    @Override
    public void initialize(Unique unique) {
        this.fields = unique.fields();
        this.messages = unique.messages();
    }
}
